#ifndef __CORE_BOX_H__
#define __CORE_BOX_H__
#include "Vector3.h"
#include "Matrix3.h"

namespace Core
{
	class rtBounds;
	class rtPlane;
	class rtSphere;
	class rtRotation;

	class rtBox
	{
	public:
		rtBox(void);
		explicit rtBox(const rtVector3& center, const rtVector3& extents, const rtMatrix3& axis);
		explicit rtBox(const rtVector3& point);
		explicit rtBox(const rtBounds& bounds);
		explicit rtBox(const rtBounds& bounds, const rtVector3& origin, const rtMatrix3& axis);

		static   rtBox box_zero;

		rtBox			operator + (const rtVector3& t) const;
		rtBox& 			operator += (const rtVector3& t);
		rtBox			operator * (const rtMatrix3& r) const;
		rtBox& 			operator *= (const rtMatrix3& r);
		rtBox			operator + (const rtBox& a) const;
		rtBox& 			operator += (const rtBox& a);
		rtBox			operator - (const rtBox& a) const;
		rtBox& 			operator -= (const rtBox& a);

		bool			compare(const rtBox& a) const;
		bool			compare(const rtBox& a, const float epsilon) const;
		bool			operator == (const rtBox& a) const;
		bool			operator != (const rtBox& a) const;

		void			clear(void);
		void			zero(void);

		const rtVector3& 	getCenter(void) const;
		const rtVector3& 	getExtents(void) const;
		const rtMatrix3& 	getAxis(void) const;
		float			getVolume(void) const;
		bool			isCleared(void) const;

		bool			addPoint(const rtVector3& v);
		bool			addBox(const rtBox& a);
		rtBox			expand(const float d) const;
		rtBox& 			expandSelf(const float d);
		rtBox			translate(const rtVector3& translation) const;
		rtBox& 			translateSelf(const rtVector3& translation);
		rtBox			rotate(const rtMatrix3& rotation) const;
		rtBox& 			rotateSelf(const rtMatrix3& rotation);

		float			planeDistance(const rtPlane& plane) const;
		int				planeSide(const rtPlane& plane, const float epsilon = ON_EPSILON) const;

		bool			containsPoint(const rtVector3& p) const;
		bool			intersectsBox(const rtBox& a) const;
		bool			lineIntersection(const rtVector3& start, const rtVector3& end) const;
		bool			rayIntersection(const rtVector3& start, const rtVector3& dir, float& scale1, float& scale2) const;

		
		void			fromPointTranslation(const rtVector3& point, const rtVector3& translation);
		void			fromBoxTranslation(const rtBox& box, const rtVector3& translation);
		
		void			fromPointRotation(const rtVector3& point, const rtRotation& rotation);
		void			fromBoxRotation(const rtBox& box, const rtRotation& rotation);

		void			toPoints(rtVector3 points[8]) const;
		rtSphere		toSphere(void) const;

		void			axisProjection(const rtVector3& dir, float& min, float& max) const;
		void			axisProjection(const rtMatrix3& ax, rtBounds& bounds) const;


	private:
		rtVector3			m_Center;
		rtVector3			m_Extents;
		rtMatrix3			m_Axis;
	};
}
#endif


